home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Applications / P4⁄Mac 1.0 / Mac source / pcom1⁄m.p < prev    next >
Encoding:
Text File  |  1994-07-28  |  27.0 KB  |  1,198 lines  |  [TEXT/PJMM]

  1. unit pcom1;
  2. interface
  3.  
  4.     const
  5.         displimit = 20;
  6.         maxlevel = 10;
  7.         intsize = 1;
  8.         intal = 1;
  9.         realsize = 1;
  10.         realal = 1;
  11.         charsize = 1;
  12.         charal = 1;
  13.         charmax = 1;
  14.         boolsize = 1;
  15.         boolal = 1;
  16.         ptrsize = 1;
  17.         adral = 1;
  18.         setsize = 1;
  19.         setal = 1;
  20.         stackal = 1;
  21.         stackelsize = 1;
  22.         strglgth = 16;
  23.         sethigh = 47;
  24.         setlow = 0;
  25.         ordmaxchar = 63;
  26.         ordminchar = 0;
  27.         maxint = 32767;
  28.         lcaftermarkstack = 5;
  29.         fileal = charal;
  30.    (* stackelsize = minimum size for 1 stackelement}
  31. {          = k*stackal}
  32. {      stackal     = scm(all other al-constants)}
  33. {      charmax     = scm(charsize,charal)}
  34. {            scm = smallest common multiple}
  35. {      lcaftermarkstack >= 4*ptrsize+max(x-size)}
  36. {            = k1*stackelsize      *)
  37.         maxstack = 1;
  38.         parmal = stackal;
  39.         parmsize = stackelsize;
  40.         recal = stackal;
  41.         filebuffer = 4;
  42.         maxaddr = maxint;
  43.  
  44.  
  45.  
  46.     type                            (*describing:*)
  47.                                 (*************)
  48.  
  49.         marktype = ^integer;
  50.                                 (*basic symbols*)
  51.                                 (***************)
  52.  
  53.         symbol = (ident, intconst, realconst, stringconst, notsy, mulop, addop, relop, lparent, rparent, lbrack, rbrack, comma, semicolon, period, arrow, colon, becomes, labelsy, constsy, typesy, varsy, funcsy, progsy, procsy, setsy, packedsy, arraysy, recordsy, filesy, forwardsy, beginsy, ifsy, casesy, repeatsy, whilesy, forsy, withsy, gotosy, endsy, elsesy, untilsy, ofsy, dosy, tosy, downtosy, thensy, othersy);
  54.         operator = (mul, rdiv, andop, idiv, imod, plus, minus, orop, ltop, leop, geop, gtop, neop, eqop, inop, noop);
  55.         setofsys = set of symbol;
  56.         chtp = (letter, number, special, illegal, chstrquo, chcolon, chperiod, chlt, chgt, chlparen, chspace);
  57.  
  58.                                 (*constants*)
  59.                                 (***********)
  60.         setty = set of setlow..sethigh;
  61.         cstclass = (reel, pset, strg);
  62.         csp = ^constant;
  63.         constant = record
  64.                 case cclass : cstclass of
  65.                     reel: (
  66.                             rval: packed array[1..strglgth] of char
  67.                     );
  68.                     pset: (
  69.                             pval: setty
  70.                     );
  71.                     strg: (
  72.                             slgth: 0..strglgth;
  73.                             sval: packed array[1..strglgth] of char
  74.                     )
  75.             end;
  76.  
  77.         valu = record
  78.                 case intval : boolean of  (*intval never set nor tested*)
  79.                     true: (
  80.                             ival: integer
  81.                     );
  82.                     false: (
  83.                             valp: csp
  84.                     )
  85.             end;
  86.  
  87.                                (*data structures*)
  88.                                (*****************)
  89.         levrange = 0..maxlevel;
  90.         addrrange = 0..maxaddr;
  91.         structform = (scalar, subrange, pointer, power, arrays, records, files, tagfld, variant);
  92.         declkind = (standard, declared);
  93.         stp = ^structure;
  94.         ctp = ^identifier;
  95.  
  96.         structure = packed record
  97.                 marked: boolean;   (*for test phase only*)
  98.                 size: addrrange;
  99.                 case form : structform of
  100.                     scalar: (
  101.                             case scalkind : declkind of
  102.                                 declared: (
  103.                                         fconst: ctp
  104.                                 );
  105.                                 standard: (
  106.                                 )
  107.                     );
  108.                     subrange: (
  109.                             rangetype: stp;
  110.                             min, max: valu
  111.                     );
  112.                     pointer: (
  113.                             eltype: stp
  114.                     );
  115.                     power: (
  116.                             elset: stp
  117.                     );
  118.                     arrays: (
  119.                             aeltype, inxtype: stp
  120.                     );
  121.                     records: (
  122.                             fstfld: ctp;
  123.                             recvar: stp
  124.                     );
  125.                     files: (
  126.                             filtype: stp
  127.                     );
  128.                     tagfld: (
  129.                             tagfieldp: ctp;
  130.                             fstvar: stp
  131.                     );
  132.                     variant: (
  133.                             nxtvar, subvar: stp;
  134.                             varval: valu
  135.                     )
  136.             end;
  137.  
  138.                                 (*names*)
  139.                                 (*******)
  140.  
  141.         idclass = (types, konst, vars, field, proc, func);
  142.         setofids = set of idclass;
  143.         idkind = (actual, formal);
  144.         alpha = packed array[1..8] of char;
  145.  
  146.         identifier = packed record
  147.                 name: alpha;
  148.                 llink, rlink: ctp;
  149.                 idtype: stp;
  150.                 next: ctp;
  151.                 case klass : idclass of
  152.                     types: (
  153.                     );
  154.                     konst: (
  155.                             values: valu
  156.                     );
  157.                     vars: (
  158.                             vkind: idkind;
  159.                             vlev: levrange;
  160.                             vaddr: addrrange
  161.                     );
  162.                     field: (
  163.                             fldaddr: addrrange
  164.                     );
  165.                     proc, func: (
  166.                             case pfdeckind : declkind of
  167.                                 standard: (
  168.                                         key: 1..15
  169.                                 );
  170.                                 declared: (
  171.                                         pflev: levrange;
  172.                                         pfname: integer;
  173.                                         case pfkind : idkind of
  174.                                             actual: (
  175.                                                     forwdecl, externl: boolean
  176.                                             );
  177.                                             formal: (
  178.                                             )
  179.                                 )
  180.                     )
  181.             end;
  182.  
  183.  
  184.         disprange = 0..displimit;
  185.         where = (blck, crec, vrec, rec);
  186.  
  187.                                 (*expressions*)
  188.                                 (*************)
  189.         attrkind = (cst, varbl, expr);
  190.         vaccess = (drct, indrct, inxd);
  191.  
  192.         attr = record
  193.                 typtr: stp;
  194.                 case kind : attrkind of
  195.                     cst: (
  196.                             cval: valu
  197.                     );
  198.                     varbl: (
  199.                             case access : vaccess of
  200.                                 drct: (
  201.                                         vlevel: levrange;
  202.                                         dplmt: addrrange
  203.                                 );
  204.                                 indrct: (
  205.                                         idplmt: addrrange
  206.                                 )
  207.                     )
  208.             end;
  209.  
  210.         testp = ^testpointer;
  211.         testpointer = packed record
  212.                 elt1, elt2: stp;
  213.                 lasttestp: testp
  214.             end;
  215.  
  216.                                  (*labels*)
  217.                                  (********)
  218.         lbp = ^labl;
  219.         labl = record
  220.                 nextlab: lbp;
  221.                 defined: boolean;
  222.                 labval, labname: integer
  223.             end;
  224.  
  225.         extfilep = ^filerec;
  226.         filerec = record
  227.                 filename: alpha;
  228.                 nextfile: extfilep
  229.             end;
  230.  
  231. (*-------------------------------------------------------------------------*)
  232.  
  233.     var
  234.         prr: text; (* comment this out when compiling with pcom *)
  235.                     (*returned by source program scanner}
  236. {                     insymbol:}
  237. {                     **********)
  238.  
  239.         sy: symbol;             (*last symbol*)
  240.         op: operator;           (*classification of last symbol*)
  241.         val: valu;              (*value of last constant*)
  242.         lgth: integer;          (*length of last string constant*)
  243.         id: alpha;              (*last identifier (possibly truncated)*)
  244.         kk: 1..8;               (*nr of chars in last identifier*)
  245.         ch: char;               (*last character*)
  246.         eol: boolean;           (*end of line flag*)
  247.  
  248.  
  249.                     (*counters:*)
  250.                     (***********)
  251.  
  252.         chcnt: integer;         (*character counter*)
  253.         lc, ic: addrrange;           (*data location and instruction counter*)
  254.         linecount: integer;
  255.  
  256.  
  257.                     (*switches:*)
  258.                     (***********)
  259.  
  260.         dp,                 (*declaration part*)
  261.         prterr,             (*to allow forward references in pointer type}
  262. {                      declaration by suppressing error message*)
  263.         list, prcode, prtables: boolean;  (*output options for}
  264. {                    -- source program listing}
  265. {                    -- printing symbolic code}
  266. {                    -- displaying ident and struct tables}
  267. {                    --> procedure option*)
  268.         debug: boolean;
  269.  
  270.  
  271.                     (*pointers:*)
  272.                     (***********)
  273.         parmptr, intptr, realptr, charptr, boolptr, nilptr, textptr: stp;    (*pointers to entries of standard ids*)
  274.         utypptr, ucstptr, uvarptr, ufldptr, uprcptr, ufctptr,    (*pointers to entries for undeclared ids*)
  275.         fwptr: ctp;             (*head of chain of forw decl type ids*)
  276.         fextfilep: extfilep;        (*head of chain of external files*)
  277.         globtestp: testp;           (*last testpointer*)
  278.  
  279.  
  280.                     (*bookkeeping of declaration levels:*)
  281.                     (************************************)
  282.  
  283.         level: levrange;        (*current static level*)
  284.         disx,               (*level of last id searched by searchid*)
  285.         top: disprange;         (*top of display*)
  286.  
  287.         display:            (*where:   means:*)
  288.         array[disprange] of packed record           (*=blck:   id is variable id*)
  289.                 fname: ctp;
  290.                 flabel: lbp;  (*=crec:   id is field id in record with*)
  291.                 case occur : where of      (*     constant address*)
  292.                     crec: (
  293.                             clev: levrange;  (*=vrec:   id is field id in record with*)
  294.                             cdspl: addrrange
  295.                     );(*     variable address*)
  296.                     vrec: (
  297.                             vdspl: addrrange
  298.                     )
  299.             end;              (* --> procedure withstatement*)
  300.  
  301.  
  302.                     (*error messages:*)
  303.                     (*****************)
  304.  
  305.         errinx: 0..10;          (*nr of errors in current source line*)
  306.         errlist: array[1..10] of packed record
  307.                 pos: integer;
  308.                 nmr: 1..400
  309.             end;
  310.  
  311.  
  312.  
  313.                     (*expression compilation:*)
  314.                     (*************************)
  315.  
  316.         gattr: attr;            (*describes the expr currently compiled*)
  317.  
  318.  
  319.                     (*structured constants:*)
  320.                     (***********************)
  321.  
  322.         constbegsys, simptypebegsys, typebegsys, blockbegsys, selectsys, facbegsys, statbegsys, typedels: setofsys;
  323.         chartp: array[char] of chtp;
  324.         rw: array[1..35] of alpha;(*nr. of res. words*)
  325.         frw: array[1..9] of 1..36;(*nr. of res. words + 1*)
  326.         rsy: array[1..35] of symbol;(*nr. of res. words*)
  327.         ssy: array[char] of symbol;
  328.         rop: array[1..35] of operator;(*nr. of res. words*)
  329.         sop: array[char] of operator;
  330.         na: array[1..35] of alpha;
  331.         mn: array[0..60] of packed array[1..4] of char;
  332.         sna: array[1..23] of packed array[1..4] of char;
  333.         cdx: array[0..60] of -4..+4;
  334.         pdx: array[1..23] of -7..+7;
  335.         ordint: array[char] of integer;
  336.  
  337.         intlabel, mxint10, digmax: integer;
  338.  
  339.  
  340.     procedure mark (var p: marktype);
  341.     procedure release (p: marktype);
  342.     procedure endofline;
  343.     procedure error (ferrnr: integer);
  344.     procedure insymbol;
  345.     procedure enterid (fcp: ctp);
  346.     procedure searchsection (fcp: ctp; var fcp1: ctp);
  347.     procedure searchid (fidcls: setofids; var fcp: ctp);
  348.     procedure getbounds (fsp: stp; var fmin, fmax: integer);
  349.     function alignquot (fsp: stp): integer;
  350.     procedure align (fsp: stp; var flc: addrrange);
  351.     procedure printtables (fb: boolean);
  352.     procedure genlabel (var nxtlab: integer);
  353.  
  354.  
  355.  
  356. implementation
  357.  
  358. (*-------------------------------------------------------------------------*)
  359.     procedure mark (var p: marktype);
  360.     begin
  361.     end;
  362.     procedure release (p: marktype);
  363.     begin
  364.     end;
  365.  
  366.     procedure endofline;
  367.         var
  368.             lastpos, freepos, currpos, currnmr, f, k: integer;
  369.     begin
  370.         if errinx > 0 then   (*output error messages*)
  371.             begin
  372.                 write(output, linecount : 6, ' ****  ' : 9);
  373.                 lastpos := 0;
  374.                 freepos := 1;
  375.                 for k := 1 to errinx do
  376.                     begin
  377.                         with errlist[k] do
  378.                             begin
  379.                                 currpos := pos;
  380.                                 currnmr := nmr
  381.                             end;
  382.                         if currpos = lastpos then
  383.                             write(output, ',')
  384.                         else
  385.                             begin
  386.                                 while freepos < currpos do
  387.                                     begin
  388.                                         write(output, ' ');
  389.                                         freepos := freepos + 1
  390.                                     end;
  391.                                 write(output, '^');
  392.                                 lastpos := currpos
  393.                             end;
  394.                         if currnmr < 10 then
  395.                             f := 1
  396.                         else if currnmr < 100 then
  397.                             f := 2
  398.                         else
  399.                             f := 3;
  400.                         write(output, currnmr : f);
  401.                         freepos := freepos + f + 1
  402.                     end;
  403.                 writeln(output);
  404.                 errinx := 0
  405.             end;
  406.         linecount := linecount + 1;
  407.         if list and (not eof(input)) then
  408.             begin
  409.                 write(output, linecount : 6, '  ' : 2);
  410.                 if dp then
  411.                     write(output, lc : 7)
  412.                 else
  413.                     write(output, ic : 7);
  414.                 write(output, ' ')
  415.             end;
  416.         chcnt := 0
  417.     end;  (*endofline*)
  418.  
  419.     procedure error (ferrnr: integer);
  420.     begin
  421.         if errinx >= 9 then
  422.             begin
  423.                 errlist[10].nmr := 255;
  424.                 errinx := 10
  425.             end
  426.         else
  427.             begin
  428.                 errinx := errinx + 1;
  429.                 errlist[errinx].nmr := ferrnr
  430.             end;
  431.         errlist[errinx].pos := chcnt
  432.     end; (*error*)
  433.  
  434.     procedure insymbol;
  435.     (*read next basic symbol of source program and return its}
  436. {    description in the global variables sy, op, id, val and lgth*)
  437.         label
  438.             1, 2, 3;
  439.         var
  440.             i, k: integer;
  441.             digit: packed array[1..strglgth] of char;
  442.             aString: packed array[1..strglgth] of char;
  443.             lvp: csp;
  444.             test: boolean;
  445.  
  446.         procedure nextch;
  447.         begin
  448.             if eol then
  449.                 begin
  450.                     if list then
  451.                         writeln(output);
  452.                     endofline
  453.                 end;
  454.             if not eof(input) then
  455.                 begin
  456.                     eol := eoln(input);
  457.                     read(input, ch);
  458.                     if list then
  459.                         write(output, ch);
  460.                     chcnt := chcnt + 1
  461.                 end
  462.             else
  463.                 begin
  464.                     writeln(output, '   *** eof ', 'encountered');
  465.                     test := false
  466.                 end
  467.         end;
  468.  
  469.         procedure options;
  470.         begin
  471.             repeat
  472.                 nextch;
  473.                 if ch <> '*' then
  474.                     begin
  475.                         if ch = 't' then
  476.                             begin
  477.                                 nextch;
  478.                                 prtables := ch = '+'
  479.                             end
  480.                         else if ch = 'l' then
  481.                             begin
  482.                                 nextch;
  483.                                 list := ch = '+';
  484.                                 if not list then
  485.                                     writeln(output)
  486.                             end
  487.                         else if ch = 'd' then
  488.                             begin
  489.                                 nextch;
  490.                                 debug := ch = '+'
  491.                             end
  492.                         else if ch = 'c' then
  493.                             begin
  494.                                 nextch;
  495.                                 prcode := ch = '+'
  496.                             end;
  497.                         nextch
  498.                     end
  499.             until ch <> ','
  500.         end; (*options*)
  501.  
  502.     begin (*insymbol*)
  503. 1:
  504.         repeat
  505.             while ((ch = ' ') or (ch = '    ')) and not eol do
  506.                 nextch;
  507.             test := eol;
  508.             if test then
  509.                 nextch
  510.         until not test;
  511.         if chartp[ch] = illegal then
  512.             begin
  513.                 sy := othersy;
  514.                 op := noop;
  515.                 error(399);
  516.                 nextch
  517.             end
  518.         else
  519.             case chartp[ch] of
  520.                 letter: 
  521.                     begin
  522.                         k := 0;
  523.                         repeat
  524.                             if k < 8 then
  525.                                 begin
  526.                                     k := k + 1;
  527.                                     id[k] := ch
  528.                                 end;
  529.                             nextch
  530.                         until chartp[ch] in [special, illegal, chstrquo, chcolon, chperiod, chlt, chgt, chlparen, chspace];
  531.                         if k >= kk then
  532.                             kk := k
  533.                         else
  534.                             repeat
  535.                                 id[kk] := ' ';
  536.                                 kk := kk - 1
  537.                             until kk = k;
  538.                         for i := frw[k] to frw[k + 1] - 1 do
  539.                             if rw[i] = id then
  540.                                 begin
  541.                                     sy := rsy[i];
  542.                                     op := rop[i];
  543.                                     goto 2
  544.                                 end;
  545.                         sy := ident;
  546.                         op := noop;
  547. 2:
  548.                     end;
  549.                 number: 
  550.                     begin
  551.                         op := noop;
  552.                         i := 0;
  553.                         repeat
  554.                             i := i + 1;
  555.                             if i <= digmax then
  556.                                 digit[i] := ch;
  557.                             nextch
  558.                         until chartp[ch] <> number;
  559.                         if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  560.                             begin
  561.                                 k := i;
  562.                                 if ch = '.' then
  563.                                     begin
  564.                                         k := k + 1;
  565.                                         if k <= digmax then
  566.                                             digit[k] := ch;
  567.                                         nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  568.                                         if chartp[ch] <> number then
  569.                                             error(201)
  570.                                         else
  571.                                             repeat
  572.                                                 k := k + 1;
  573.                                                 if k <= digmax then
  574.                                                     digit[k] := ch;
  575.                                                 nextch
  576.                                             until chartp[ch] <> number
  577.                                     end;
  578.                                 if ch = 'e' then
  579.                                     begin
  580.                                         k := k + 1;
  581.                                         if k <= digmax then
  582.                                             digit[k] := ch;
  583.                                         nextch;
  584.                                         if (ch = '+') or (ch = '-') then
  585.                                             begin
  586.                                                 k := k + 1;
  587.                                                 if k <= digmax then
  588.                                                     digit[k] := ch;
  589.                                                 nextch
  590.                                             end;
  591.                                         if chartp[ch] <> number then
  592.                                             error(201)
  593.                                         else
  594.                                             repeat
  595.                                                 k := k + 1;
  596.                                                 if k <= digmax then
  597.                                                     digit[k] := ch;
  598.                                                 nextch
  599.                                             until chartp[ch] <> number
  600.                                     end;
  601.                                 new(lvp, reel);
  602.                                 sy := realconst;
  603.                                 lvp^.cclass := reel;
  604.                                 with lvp^ do
  605.                                     begin
  606.                                         for i := 1 to strglgth do
  607.                                             rval[i] := ' ';
  608.                                         if k <= digmax then
  609.                                             for i := 2 to k + 1 do
  610.                                                 rval[i] := digit[i - 1]
  611.                                         else
  612.                                             begin
  613.                                                 error(203);
  614.                                                 rval[2] := '0';
  615.                                                 rval[3] := '.';
  616.                                                 rval[4] := '0'
  617.                                             end
  618.                                     end;
  619.                                 val.valp := lvp
  620.                             end
  621.                         else
  622. 3:
  623.                             begin
  624.                                 if i > digmax then
  625.                                     begin
  626.                                         error(203);
  627.                                         val.ival := 0
  628.                                     end
  629.                                 else
  630.                                     with val do
  631.                                         begin
  632.                                             ival := 0;
  633.                                             for k := 1 to i do
  634.                                                 begin
  635.                                                     if ival <= mxint10 then
  636.                                                         ival := ival * 10 + ordint[digit[k]]
  637.                                                     else
  638.                                                         begin
  639.                                                             error(203);
  640.                                                             ival := 0
  641.                                                         end
  642.                                                 end;
  643.                                             sy := intconst
  644.                                         end
  645.                             end
  646.                     end;
  647.                 chstrquo: 
  648.                     begin
  649.                         lgth := 0;
  650.                         sy := stringconst;
  651.                         op := noop;
  652.                         repeat
  653.                             repeat
  654.                                 nextch;
  655.                                 lgth := lgth + 1;
  656.                                 if lgth <= strglgth then
  657.                                     aString[lgth] := ch
  658.                             until (eol) or (ch = '''');
  659.                             if eol then
  660.                                 error(202)
  661.                             else
  662.                                 nextch
  663.                         until ch <> '''';
  664.                         lgth := lgth - 1;   (*now lgth = nr of chars in aString*)
  665.                         if lgth = 0 then
  666.                             error(205)
  667.                         else if lgth = 1 then
  668.                             val.ival := ord(aString[1])
  669.                         else
  670.                             begin
  671.                                 new(lvp, strg);
  672.                                 lvp^.cclass := strg;
  673.                                 if lgth > strglgth then
  674.                                     begin
  675.                                         error(399);
  676.                                         lgth := strglgth
  677.                                     end;
  678.                                 with lvp^ do
  679.                                     begin
  680.                                         slgth := lgth;
  681.                                         for i := 1 to lgth do
  682.                                             sval[i] := aString[i]
  683.                                     end;
  684.                                 val.valp := lvp
  685.                             end
  686.                     end;
  687.                 chcolon: 
  688.                     begin
  689.                         op := noop;
  690.                         nextch;
  691.                         if ch = '=' then
  692.                             begin
  693.                                 sy := becomes;
  694.                                 nextch
  695.                             end
  696.                         else
  697.                             sy := colon
  698.                     end;
  699.                 chperiod: 
  700.                     begin
  701.                         op := noop;
  702.                         nextch;
  703.                         if ch = '.' then
  704.                             begin
  705.                                 sy := colon;
  706.                                 nextch
  707.                             end
  708.                         else
  709.                             sy := period
  710.                     end;
  711.                 chlt: 
  712.                     begin
  713.                         nextch;
  714.                         sy := relop;
  715.                         if ch = '=' then
  716.                             begin
  717.                                 op := leop;
  718.                                 nextch
  719.                             end
  720.                         else if ch = '>' then
  721.                             begin
  722.                                 op := neop;
  723.                                 nextch
  724.                             end
  725.                         else
  726.                             op := ltop
  727.                     end;
  728.                 chgt: 
  729.                     begin
  730.                         nextch;
  731.                         sy := relop;
  732.                         if ch = '=' then
  733.                             begin
  734.                                 op := geop;
  735.                                 nextch
  736.                             end
  737.                         else
  738.                             op := gtop
  739.                     end;
  740.                 chlparen: 
  741.                     begin
  742.                         nextch;
  743.                         if ch = '*' then
  744.                             begin
  745.                                 nextch;
  746.                                 if ch = '$' then
  747.                                     options;
  748.                                 repeat
  749.                                     while (ch <> '*') and not eof(input) do
  750.                                         nextch;
  751.                                     nextch
  752.                                 until (ch = ')') or eof(input);
  753.                                 nextch;
  754.                                 goto 1
  755.                             end;
  756.                         sy := lparent;
  757.                         op := noop
  758.                     end;
  759.                 special: 
  760.                     begin
  761.                         sy := ssy[ch];
  762.                         op := sop[ch];
  763.                         nextch
  764.                     end;
  765.                 chspace: 
  766.                     sy := othersy
  767.             end (*case*)
  768.     end; (*insymbol*)
  769.  
  770.     procedure enterid (fcp: ctp);
  771.     (*enter id pointed at by fcp into the name-table,}
  772. {     which on each declaration level is organised as}
  773. {     an unbalanced binary tree*)
  774.         var
  775.             nam: alpha;
  776.             lcp, lcp1: ctp;
  777.             lleft: boolean;
  778.     begin
  779.         nam := fcp^.name;
  780.         lcp := display[top].fname;
  781.         if lcp = nil then
  782.             display[top].fname := fcp
  783.         else
  784.             begin
  785.                 repeat
  786.                     lcp1 := lcp;
  787.                     if lcp^.name = nam then   (*name conflict, follow right link*)
  788.                         begin
  789.                             error(101);
  790.                             lcp := lcp^.rlink;
  791.                             lleft := false
  792.                         end
  793.                     else if lcp^.name < nam then
  794.                         begin
  795.                             lcp := lcp^.rlink;
  796.                             lleft := false
  797.                         end
  798.                     else
  799.                         begin
  800.                             lcp := lcp^.llink;
  801.                             lleft := true
  802.                         end
  803.                 until lcp = nil;
  804.                 if lleft then
  805.                     lcp1^.llink := fcp
  806.                 else
  807.                     lcp1^.rlink := fcp
  808.             end;
  809.         fcp^.llink := nil;
  810.         fcp^.rlink := nil
  811.     end; (*enterid*)
  812.  
  813.     procedure searchsection (fcp: ctp; var fcp1: ctp);
  814.     (*to find record fields and forward declared procedure id's}
  815. {     --> procedure proceduredeclaration}
  816. {     --> procedure selector*)
  817.         label
  818.             1;
  819.     begin
  820.         while fcp <> nil do
  821.             if fcp^.name = id then
  822.                 goto 1
  823.             else if fcp^.name < id then
  824.                 fcp := fcp^.rlink
  825.             else
  826.                 fcp := fcp^.llink;
  827. 1:
  828.         fcp1 := fcp
  829.     end; (*searchsection*)
  830.  
  831.     procedure searchid (fidcls: setofids; var fcp: ctp);
  832.         label
  833.             1;
  834.         var
  835.             lcp: ctp;
  836.             localDisx: disprange; {Must have a local variable for "for"; disx is assigned once we leave the loop}
  837.     begin
  838.         for localDisx := top downto 0 do
  839.             begin
  840.                 lcp := display[localDisx].fname;
  841.                 while lcp <> nil do
  842.                     if lcp^.name = id then
  843.                         if lcp^.klass in fidcls then
  844.                             goto 1
  845.                         else
  846.                             begin
  847.                                 if prterr then
  848.                                     error(103);
  849.                                 lcp := lcp^.rlink
  850.                             end
  851.                     else if lcp^.name < id then
  852.                         lcp := lcp^.rlink
  853.                     else
  854.                         lcp := lcp^.llink
  855.             end;
  856.     (*search not successful; suppress error message in case}
  857. {     of forward referenced type id in pointer type definition}
  858. {     --> procedure simpletype*)
  859.         if prterr then
  860.             begin
  861.                 error(104);
  862.     (*to avoid returning nil, reference an entry}
  863. {     for an undeclared id of appropriate class}
  864. {     --> procedure enterundecl*)
  865.                 if types in fidcls then
  866.                     lcp := utypptr
  867.                 else if vars in fidcls then
  868.                     lcp := uvarptr
  869.                 else if field in fidcls then
  870.                     lcp := ufldptr
  871.                 else if konst in fidcls then
  872.                     lcp := ucstptr
  873.                 else if proc in fidcls then
  874.                     lcp := uprcptr
  875.                 else
  876.                     lcp := ufctptr;
  877.             end;
  878. 1:
  879.         disx := localDisx; {Export local var for loop}
  880.         fcp := lcp
  881.     end; (*searchid*)
  882.  
  883.     procedure getbounds (fsp: stp; var fmin, fmax: integer);
  884.     (*get internal bounds of subrange or scalar type*)
  885.     (*assume fsp<>intptr and fsp<>realptr*)
  886.     begin
  887.         fmin := 0;
  888.         fmax := 0;
  889.         if fsp <> nil then
  890.             with fsp^ do
  891.                 if form = subrange then
  892.                     begin
  893.                         fmin := min.ival;
  894.                         fmax := max.ival
  895.                     end
  896.                 else if fsp = charptr then
  897.                     begin
  898.                         fmin := ordminchar;
  899.                         fmax := ordmaxchar
  900.                     end
  901.                 else if fconst <> nil then
  902.                     fmax := fconst^.values.ival
  903.     end; (*getbounds*)
  904.  
  905.     function alignquot (fsp: stp): integer;
  906.     begin
  907.         alignquot := 1;
  908.         if fsp <> nil then
  909.             with fsp^ do
  910.                 case form of
  911.                     scalar: 
  912.                         if fsp = intptr then
  913.                             alignquot := intal
  914.                         else if fsp = boolptr then
  915.                             alignquot := boolal
  916.                         else if scalkind = declared then
  917.                             alignquot := intal
  918.                         else if fsp = charptr then
  919.                             alignquot := charal
  920.                         else if fsp = realptr then
  921.                             alignquot := realal
  922.                         else (*parmptr*)
  923.                             alignquot := parmal;
  924.                     subrange: 
  925.                         alignquot := alignquot(rangetype);
  926.                     pointer: 
  927.                         alignquot := adral;
  928.                     power: 
  929.                         alignquot := setal;
  930.                     files: 
  931.                         alignquot := fileal;
  932.                     arrays: 
  933.                         alignquot := alignquot(aeltype);
  934.                     records: 
  935.                         alignquot := recal;
  936.                     variant, tagfld: 
  937.                         error(501)
  938.                 end
  939.     end; (*alignquot*)
  940.  
  941.     procedure align (fsp: stp; var flc: addrrange);
  942.         var
  943.             k, l: integer;
  944.     begin
  945.         k := alignquot(fsp);
  946.         l := flc - 1;
  947.         flc := l + k - (k + l) mod k
  948.     end; (*align*)
  949.  
  950.     procedure printtables (fb: boolean);
  951.     (*print data structure and name table*)
  952.         var
  953.             i, lim: disprange;
  954.  
  955.         procedure marker;
  956.       (*mark data structure entries to avoid multiple printout*)
  957.             var
  958.                 i: integer;
  959.  
  960.             procedure markctp (fp: ctp);
  961.             forward;
  962.  
  963.             procedure markstp (fp: stp);
  964.     (*mark data structures, prevent cycles*)
  965.             begin
  966.                 if fp <> nil then
  967.                     with fp^ do
  968.                         begin
  969.                             marked := true;
  970.                             case form of
  971.                                 scalar: 
  972.                                     ;
  973.                                 subrange: 
  974.                                     markstp(rangetype);
  975.                                 pointer: 
  976.                                     ;  (*don't mark eltype: cycle possible; will be marked}
  977. {            anyway, if fp = true*)
  978.                                 power: 
  979.                                     markstp(elset);
  980.                                 arrays: 
  981.                                     begin
  982.                                         markstp(aeltype);
  983.                                         markstp(inxtype)
  984.                                     end;
  985.                                 records: 
  986.                                     begin
  987.                                         markctp(fstfld);
  988.                                         markstp(recvar)
  989.                                     end;
  990.                                 files: 
  991.                                     markstp(filtype);
  992.                                 tagfld: 
  993.                                     markstp(fstvar);
  994.                                 variant: 
  995.                                     begin
  996.                                         markstp(nxtvar);
  997.                                         markstp(subvar)
  998.                                     end
  999.                             end (*case*)
  1000.                         end (*with*)
  1001.             end; (*markstp*)
  1002.  
  1003.             procedure markctp;
  1004.             begin
  1005.                 if fp <> nil then
  1006.                     with fp^ do
  1007.                         begin
  1008.                             markctp(llink);
  1009.                             markctp(rlink);
  1010.                             markstp(idtype)
  1011.                         end
  1012.             end; (*markctp*)
  1013.  
  1014.         begin (*marker*)
  1015.             for i := top downto lim do
  1016.                 markctp(display[i].fname)
  1017.         end; (*marker*)
  1018.  
  1019.         procedure followctp (fp: ctp);
  1020.         forward;
  1021.  
  1022.         procedure followstp (fp: stp);
  1023.         begin
  1024.             if fp <> nil then
  1025.                 with fp^ do
  1026.                     if marked then
  1027.                         begin
  1028.                             marked := false;
  1029.                             write(output, ' ' : 4, ord(fp) : 6, size : 10);
  1030.                             case form of
  1031.                                 scalar: 
  1032.                                     begin
  1033.                                         write(output, 'scalar' : 10);
  1034.                                         if scalkind = standard then
  1035.                                             write(output, 'standard' : 10)
  1036.                                         else
  1037.                                             write(output, 'declared' : 10, ' ' : 4, ord(fconst) : 6);
  1038.                                         writeln(output)
  1039.                                     end;
  1040.                                 subrange: 
  1041.                                     begin
  1042.                                         write(output, 'subrange' : 10, ' ' : 4, ord(rangetype) : 6);
  1043.                                         if rangetype <> realptr then
  1044.                                             write(output, min.ival, max.ival)
  1045.                                         else if (min.valp <> nil) and (max.valp <> nil) then
  1046.                                             write(output, ' ', min.valp^.rval : 9, ' ', max.valp^.rval : 9);
  1047.                                         writeln(output);
  1048.                                         followstp(rangetype);
  1049.                                     end;
  1050.                                 pointer: 
  1051.                                     writeln(output, 'pointer' : 10, ' ' : 4, ord(eltype) : 6);
  1052.                                 power: 
  1053.                                     begin
  1054.                                         writeln(output, 'set' : 10, ' ' : 4, ord(elset) : 6);
  1055.                                         followstp(elset)
  1056.                                     end;
  1057.                                 arrays: 
  1058.                                     begin
  1059.                                         writeln(output, 'array' : 10, ' ' : 4, ord(aeltype) : 6, ' ' : 4, ord(inxtype) : 6);
  1060.                                         followstp(aeltype);
  1061.                                         followstp(inxtype)
  1062.                                     end;
  1063.                                 records: 
  1064.                                     begin
  1065.                                         writeln(output, 'record' : 10, ' ' : 4, ord(fstfld) : 6, ' ' : 4, ord(recvar) : 6);
  1066.                                         followctp(fstfld);
  1067.                                         followstp(recvar)
  1068.                                     end;
  1069.                                 files: 
  1070.                                     begin
  1071.                                         write(output, 'file' : 10, ' ' : 4, ord(filtype) : 6);
  1072.                                         followstp(filtype)
  1073.                                     end;
  1074.                                 tagfld: 
  1075.                                     begin
  1076.                                         writeln(output, 'tagfld' : 10, ' ' : 4, ord(tagfieldp) : 6, ' ' : 4, ord(fstvar) : 6);
  1077.                                         followstp(fstvar)
  1078.                                     end;
  1079.                                 variant: 
  1080.                                     begin
  1081.                                         writeln(output, 'variant' : 10, ' ' : 4, ord(nxtvar) : 6, ' ' : 4, ord(subvar) : 6, varval.ival);
  1082.                                         followstp(nxtvar);
  1083.                                         followstp(subvar)
  1084.                                     end
  1085.                             end (*case*)
  1086.                         end (*if marked*)
  1087.         end; (*followstp*)
  1088.  
  1089.         procedure followctp;
  1090.             var
  1091.                 i: integer;
  1092.         begin
  1093.             if fp <> nil then
  1094.                 with fp^ do
  1095.                     begin
  1096.                         write(output, ' ' : 4, ord(fp) : 6, ' ', name : 9, ' ' : 4, ord(llink) : 6, ' ' : 4, ord(rlink) : 6, ' ' : 4, ord(idtype) : 6);
  1097.                         case klass of
  1098.                             types: 
  1099.                                 write(output, 'type' : 10);
  1100.                             konst: 
  1101.                                 begin
  1102.                                     write(output, 'constant' : 10, ' ' : 4, ord(next) : 6);
  1103.                                     if idtype <> nil then
  1104.                                         if idtype = realptr then
  1105.                                             begin
  1106.                                                 if values.valp <> nil then
  1107.                                                     write(output, ' ', values.valp^.rval : 9)
  1108.                                             end
  1109.                                         else if idtype^.form = arrays then  (*stringconst*)
  1110.                                             begin
  1111.                                                 if values.valp <> nil then
  1112.                                                     begin
  1113.                                                         write(output, ' ');
  1114.                                                         with values.valp^ do
  1115.                                                             for i := 1 to slgth do
  1116.                                                                 write(output, sval[i])
  1117.                                                     end
  1118.                                             end
  1119.                                         else
  1120.                                             write(output, values.ival)
  1121.                                 end;
  1122.                             vars: 
  1123.                                 begin
  1124.                                     write(output, 'variable' : 10);
  1125.                                     if vkind = actual then
  1126.                                         write(output, 'actual' : 10)
  1127.                                     else
  1128.                                         write(output, 'formal' : 10);
  1129.                                     write(output, ' ' : 4, ord(next) : 6, vlev, ' ' : 4, vaddr : 6);
  1130.                                 end;
  1131.                             field: 
  1132.                                 write(output, 'field' : 10, ' ' : 4, ord(next) : 6, ' ' : 4, fldaddr : 6);
  1133.                             proc, func: 
  1134.                                 begin
  1135.                                     if klass = proc then
  1136.                                         write(output, 'procedure' : 10)
  1137.                                     else
  1138.                                         write(output, 'function' : 10);
  1139.                                     if pfdeckind = standard then
  1140.                                         write(output, 'standard' : 10, key : 10)
  1141.                                     else
  1142.                                         begin
  1143.                                             write(output, 'declared' : 10, ' ' : 4, ord(next) : 6);
  1144.                                             write(output, pflev, ' ' : 4, pfname : 6);
  1145.                                             if pfkind = actual then
  1146.                                                 begin
  1147.                                                     write(output, 'actual' : 10);
  1148.                                                     if forwdecl then
  1149.                                                         write(output, 'forward' : 10)
  1150.                                                     else
  1151.                                                         write(output, 'notforward' : 10);
  1152.                                                     if externl then
  1153.                                                         write(output, 'extern' : 10)
  1154.                                                     else
  1155.                                                         write(output, 'not extern' : 10);
  1156.                                                 end
  1157.                                             else
  1158.                                                 write(output, 'formal' : 10)
  1159.                                         end
  1160.                                 end
  1161.                         end; (*case*)
  1162.                         writeln(output);
  1163.                         followctp(llink);
  1164.                         followctp(rlink);
  1165.                         followstp(idtype)
  1166.                     end (*with*)
  1167.         end; (*followctp*)
  1168.  
  1169.     begin (*printtables*)
  1170.         writeln(output);
  1171.         writeln(output);
  1172.         writeln(output);
  1173.         if fb then
  1174.             lim := 0
  1175.         else
  1176.             begin
  1177.                 lim := top;
  1178.                 write(output, ' local')
  1179.             end;
  1180.         writeln(output, ' tables ');
  1181.         writeln(output);
  1182.         marker;
  1183.         for i := top downto lim do
  1184.             followctp(display[i].fname);
  1185.         writeln(output);
  1186.         if not eol then
  1187.             write(output, ' ' : chcnt + 16)
  1188.     end; (*printtables*)
  1189.  
  1190.     procedure genlabel (var nxtlab: integer);
  1191.     begin
  1192.         intlabel := intlabel + 1;
  1193.         nxtlab := intlabel
  1194.     end; (*genlabel*)
  1195.  
  1196.  
  1197.  
  1198. end.